logging = {
  info: function(){ try { console.log(arguments); } catch(e){} },
  log: function(){ try { console.log(arguments); } catch(e){} },
  error: function(){ try { console.log(arguments); } catch(e){} }
};

authorization_callback = function(){}
function create_authorization(key,idx,callback)
{
  if (callback!=null)
    authorization_callback = callback;
   window.open('/dashboard/authorize/'+key+'/'+idx,'','width=700,height=400');
}

function authorization_complete(response)
{
  if (authorization_callback!=null)
    authorization_callback(response);
}



/* daylight savings rules are for usa right now */
function impact_local_date(l)
{
	setupTimeZone()
	l = l + impact_timezone_offset*3600000;
	if(impact_daylight_savings && impact_currently_dst)
		l = l + impact_daylight_offset * 3600000;

	var d = new Date(l);
	var m    = d.getMonth()+1;
	var day  = d.getDate();
	var y    = d.getFullYear();
	var hh   = d.getHours();
	var mm   = d.getMinutes();
	if (mm < 10)
		mm = '0'+mm;

	return m+'.'+day+'.'+y+' '+hh+':'+mm
}

function impact_utc_date(d)
{
	setupTimeZone()
	l = d.getTime()
	l = l - impact_timezone_offset*3600000;
	var d = new Date(l);
	return d
}


var impact_daylight_savings = null;
var impact_timzone_offset   = null;
var impact_currently_dst    = null;
var impact_daylight_offset  = null;
function setupTimeZone() {

		if(impact_daylight_savings != null)
			return;

	   var rightNow = new Date();
	   impact_timezone_offset = -(rightNow.getTimezoneOffset()/60)
	   var date1 = new Date(rightNow.getFullYear(), 0, 1, 0, 0, 0, 0);
	   var date2 = new Date(rightNow.getFullYear(), 6, 1, 0, 0, 0, 0);
	   var temp = date1.toGMTString();
	   var date3 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
	   var temp = date2.toGMTString();
	   var date4 = new Date(temp.substring(0, temp.lastIndexOf(" ")-1));
	   var hoursDiffStdTime = (date1 - date3) / (1000 * 60 * 60);
	   var hoursDiffDaylightTime = (date2 - date4) / (1000 * 60 * 60);
	   if (hoursDiffDaylightTime == hoursDiffStdTime) {
	    	 //alert("Time zone is GMT " + hoursDiffStdTime + ".\nDaylight Saving Time is NOT observed here.");
	       impact_daylight_savings = false;
	   } else {
		   //alert("Time zone is GMT " + hoursDiffStdTime + ".\nDaylight Saving Time is observed here.")
		   //alert("diff "+hoursDiffStdTime+" "+hoursDiffDaylightTime)
		   impact_daylight_savings = true;
		   impact_daylight_offset  = -(hoursDiffDaylightTime - hoursDiffStdTime)
	   }
	currentlyDST();
}

//u.s.a. rules
function currentlyDST()
{
	var dst = 0;
	var gmt = new Date;
	var lsm = new Date;
	var lso = new Date;
	// months 0-11
	lsm.setMonth(2); // March
	// days 1-31
	lsm.setDate(11);
	var day = lsm.getDay();// day of week of 11th
	lsm.setDate(11-day); // set day 2nd Sunday
	// months 0-11
	lso.setMonth(10); // October
	// days 1-31
	lso.setDate(4);
	day = lso.getDay();// day of week of 4th
	lso.setDate(4-day); // set day 1st Sunday
	if (gmt < lsm || gmt >= lso){
	dst = 1;
	}
	if (dst == 0){
		impact_currently_dst = true;
	}
	if (dst == 1){
		impact_currently_dst = false;
	}

}





(function( $ )
{

$$$ = function($parent, class_name, t, r, b, l, callback)
{
      var p = {'position':'absolute'}
      if (t!=null) p.top = t+"px";
      if (r!=null) p.right = r+"px";
      if (b!=null) p.bottom = b+"px";
      if (l!=null) p.left = l+"px";
      var $c = $("<div></div>").css(p);
      if (class_name!=null)
        $c.addClass(class_name)
      if (callback!=null)
        $c.click(callback);
      $parent.append($c);
      return $c;
}

$$div = function($parent,class_name,callback)
{
    var $c = $("<div></div>");
    if (class_name!=null)
      $c.addClass(class_name)
    if (callback!=null)
      $c.click(callback);
    $parent.append($c);
    return $c;

}

$$label = function($parent,text,class_name)
{
    var $c = $("<div></div>");
    if (class_name!=null)
      $c.addClass(class_name)
    $c.append(text);
    $parent.append($c);
    return $c;

}


$$button = function($parent,text,event_data,callback)
{
      var $c = $('<button>'+text+'</button>');
      if (callback!=null)
        $c.click(event_data,callback);
      $parent.append($c);
      return $c;
}

$$select = function($parent,event_data,callback)
{
      var $c = $('<select></select>');
      if (callback!=null)
    	  $c.bind('change',event_data,callback)

      $c.extend({
        add_option: function(display_value,selected,value)
        {
          if (selected==null) selected=false;
          var $o = $('<option>'+display_value+"</option>");
          $c.append($o);
          if (selected)
          {
            $o.attr('selected','selected');
          }
          if(value)
        	  $o.attr('value',value)
        },
        empty: function()
        {
          $c.children().remove();
        },
        get_selected_index: function()
        {
          return $c[0].options.selectedIndex;
        },
        get_selected: function()
        {
          return $($c.children()[$c.get_selected_index()]);
        },
        get_selected_display_value: function()
        {
          return $c.get_selected().text();
        }
      });
      $parent.append($c);
      return $c;
}

$$br = function($parent)
{
      var $c = $('<br></br>');
      $parent.append($c);
      return $c;
}

$$input = function($parent,size)
{

      var $c = $('<input type="text">');
    if (size!=null)
      $c.attr("size", size)

      $c.extend({
        set_value: function(s)
        {
          $c.val(s);
        },
        get_value: function()
        {
          return $c.val();
        }
      })
      $parent.append($c);
      return $c;
}

$$date = function($parent,event_data,callback)
{
      var $c = $('<input type="text">');
      $c.datepicker();
      if (callback!=null)
        $c.bind('change',event_data,callback)

      $c.extend({

      	val:function()
      	{
			return $c.datepicker( "getDate" );
      	},
        get_date: function()
        {
          return $c.datepicker( "getDate" );
        },
        set_date: function(d)
        {
          return $c.datepicker( "setDate", d );
        }
      })
      $parent.append($c);
      return $c;
}


/**
 * manageable list
 * requires param cell_renderer a function that returns a $(jQuery) object
 *
 */

$.widget( "impact.clist",
{

  options: {
     cell_renderer: null,
     addable: true,
     deletable: true,
     reorderable: false,
     selectable: false
   },

  _create: function()
  {
    var self = this, el = this.element;
    self._value = [];
    el.css({'position':'relative'});
    self._$children = $("<div></div>").addClass('clist-children-wrapper')
    el.append(self._$children);
    if (self.options.addable)
    {
	    //self._$add = $("<div>+ Add</div>");
	    self._$add = $('<div class="dashboard-tab rounded-corners-top" style="position: relative;"><span class="click_area"><img src="/static/image/plus.png" alt="+ Add" /></span></div>');
	    self._$add.click(function(){  self._trigger( "add" ); });
	    el.append(self._$add);
    }
  },

  _destroy: function()
  {
    var self = this, el = this.element;
    el.empty()
  },

  value: function(t)
  {
    var self = this, el = this.element;
    if (t==null)
      return self._value;
    if (self.options.cell_renderer==null)
      throw new Error("error: set cell_renderer before calling set value")

    self._value = t;
    self._$children.empty()
    for (var i=0; i<self._value.length; i++)
    {
      self._add_cell( i, self._value[i] );
    }
  },

  add_value: function(t) //TODO? at index
  {
    var self = this, el = this.element;
    if (self.options.cell_renderer==null)
      throw new Error("error: set cell_renderer before calling set value")

    self._value.push(t);
    self._add_cell(self._value.length-1, t);
  },

  remove: function(index)
  {
    var self = this, el = this.element;
    if (self.options.cell_renderer==null)
      throw new Error("error: set cell_renderer before calling set value")

    self._value.splice(index,1)
    self.value(self._value);
  },

  select: function(index)
  {
    var self = this, el = this.element;
    var c = self._$children.children()[index];
    self._select_cell($(c),index);
  },

  selection_index: function(t)
  {
	  var self = this;
	console.log("!!!! "+self.selected_index+" "+t)
	  if (t!=null)
		  self.select(t);
	  else
		  return self.selected_index;
  },

  _add_cell:function(i, v)
  {
    var self = this;
    var $cell = self.options.cell_renderer(v);
    $cell.css('position','relative')
    // selectable cells trigger a select event, selected cells have cell-selected class
    if (self.options.selectable)
    {
      $cell.click(function(){
        self._select_cell($cell, i);
        self._trigger( "select", 0, { index: i, value: self._value[i] });
      });
    }
    // deletable cells trigger a delete event, a delete button is appended
    if (self.options.deletable)
    {
      var $close = $("<div>Remove</div>")
                      .addClass('ui-icon ui-icon-close')
                      .css({'position':'absolute','right': '5px', 'top': 0});
      $close.click(function(){  self._trigger( "deletef",  0, { index: i } ); });
      $cell.append($close);
    }

    self._$children.append($cell);
  },

  _select_cell: function($cell,idx)
  {
	var self = this;
	self.selected_index = idx;
    if (self._$last_selected_cell!=null)
      self._$last_selected_cell.removeClass('cell-selected');
    $cell.addClass('cell-selected');
    self._$last_selected_cell = $cell;
  }


});









/**
 * dialogs
 */


$.dialog_ok = function(title,message,yes,no,callback)
{
  $("#dialog-confirm-message").empty();
  $("#dialog-confirm-message").append(message);
  var dopts = {
    resizable: false,
    height:180,
    modal: true,
    buttons: {},
    title: title,
    draggable: false
  };
  dopts.buttons[yes] = function()
    {
      $( this ).dialog( "close" );
      callback();
    };
  dopts.buttons[no] = function()
    {
      $( this ).dialog( "close" );
    };
  $( "#dialog-confirm" ).dialog(dopts);
}



$.dialog_input = function(title,message,yes,no,callback,extra)
{
  $( "#dialog-input-field" ).val("")
  $("#dialog-input-message").empty();
  $("#dialog-input-message").append(message);
  $("#dialog-input-extra-fields").empty();
  var extra_vals = extra !=null ? extra($( "#dialog-input-extra-fields" )) : null;
  var dopts = {
    resizable: false,
    height:240,
    modal: true,
    buttons: {},
    title: title,
    draggable: false
  };
  dopts.buttons[yes] = function()
    {
      $( this ).dialog( "close" );
      var a = [];
      if (extra_vals!=null)
        for(var i=0; i<extra_vals.length; i++)
          a.push(extra_vals[i].val())
      callback($( "#dialog-input-field" ).val(), a );
    };
  dopts.buttons[no] = function()
    {
      $( this ).dialog( "close" );
    };
  $( "#dialog-input" ).dialog(dopts);
}



$.globalToLocal = function( context, globalX, globalY ){
	 // Get the position of the context element.
	 var position = context.offset();
	 // Return the X/Y in the local context.
	 return({
	 x: Math.floor( globalX - position.left ),
	 y: Math.floor( globalY - position.top )
	 });
};




/* get_json: use instead of getJSON to catch and display errors */
$.json_err_handler = function (e)
{
   // alert("ERROR:"+e);
    logging.log(e);
}
$.get_json = function(url, data, callback, err, $network_indicator)
{
    if ($network_indicator!=null)
      $network_indicator.show();
    if (err==null)
	    err = $.json_err_handler;
    var wrapcallback = function(res)
    {
      if ($network_indicator!=null)
        $network_indicator.hide();

      if (res.error)
      {
        err(res.error+"\n"+res.message)
      }
      else
      {
        callback(res);
      }
    }
    var req = {
      url: url,
      dataType: 'json',
      success: wrapcallback,
      error: err
    }
    if (data!=null)
      req.data = data;

    $.ajax(req);
}













})( jQuery );